#pragma once
/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Multi-threaded Task Base Class
 *      Provides an abstract base definition for implementing long-running tasks
 * in an independent thread with progress update events.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
#include "stdafx.h"

using namespace System;
using namespace System::Threading;
using namespace Adaptive::Foundation;

namespace Adaptive
{
	namespace Foundation
	{
		namespace Threading
		{
			/// <summary>
			/// Provides an abstract base definition for implementing long-running tasks
			/// in an independent thread with progress update events.
			/// </summary>
			public ref class MultiThreadedTaskBase abstract : public AiObjectBase
			{
			public:
				/*--------------------------------------------------------------------------------
				 * Public Event Definitions
				 *------------------------------------------------------------------------------*/
				#pragma region Public Event Definitions
				/// <summary>
				/// Occurs during task processing to update a UI or log indicating the overall task progress.
				/// </summary>
				event ProgressEventHandler^ ProgressUpdate;
				/// <summary>
				/// Occurs during task processing to update a UI or log indicating the progress of a sub-task.
				/// </summary>
				event ProgressEventHandler^ SubProgressUpdate;
				/// <summary>
				/// Occurs when a task is started.
				/// </summary>
				event EventHandler^			TaskStart;
				/// <summary>
				/// Occurs when a task is completed.
				/// </summary>
				event EventHandler^			TaskCompleted;
				/// <summary>
				/// Occurs when a task operation fails.
				/// </summary>
				event EventHandler^			TaskFailure;
				/// <summary>
				/// Occurs when a task is cancelled.
				/// </summary>
				event EventHandler^			TaskCancelled;
				/// <summary>
				/// Occurs when a task encounters an exception instance.
				/// </summary>
				event ExceptionEventHandler^ TaskException;
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Constructor / Dispose / Destructor Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Constructor / Dispose / Destructor Methods
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <remarks>
				/// This is the default constructor.
				/// </remarks>
				MultiThreadedTaskBase();
				/// <summary>
				/// Initializes a new instance of the class to the specified name.
				/// </summary>
				/// <param name="taskName">
				/// An ID or name value assigned to the object instance.
				/// </param>
				MultiThreadedTaskBase(String^ taskName);
				/// <summary>
				/// Class destructor.
				/// </summary>
				~MultiThreadedTaskBase();
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Public Properties
				 *------------------------------------------------------------------------------*/
				#pragma region Public Properties
				/// <summary>
				/// Gets a value indicating whether the task is currently being executed.
				/// </summary>
				/// <value>
				/// <b>true</b> if the asynchronous task is running; otherwise, <b>false</b>.
				/// </value>
				property bool IsRunning{ bool get(); }
				/// <summary>
				/// Gets a value indicating whether the task has been cancelled.
				/// </summary>
				/// <value>
				/// <b>true</b> if the <see cref="Cancel"/> method has already been called; otherwise, <b>false</b>.
				/// </value>
				property bool Cancelled{ bool get(); }
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Public Methods / Functions
				 *------------------------------------------------------------------------------*/
				#pragma region Public Methods / Functions
				/// <summary>
				/// Starts executing the task in a seperate thread, if not already running.
				/// </summary>
				/// <remarks>
				/// This method invokes the internal thread, if it is not already executing.  The method
				/// will return asynchronously.
				/// </remarks>
				virtual void BeginExecute();
				/// <summary>
				/// Cancels the currently executing operation.
				/// </summary>
				/// <remarks>
				/// This method sets the internal cancellation flag.  Note that the operation may or may not 
				/// cancel if the descendant method implementation(s) are blocking or have hung.
				/// </remarks>
				/// <param name="waitForOperationToComplete">
				/// A value indicating whether to block (when <b>true</b>) until the thread terminates; or return
				/// immediately (when <b>false</b>).
				/// </param>
				virtual void Cancel(bool waitForOperationToComplete);
				/// <summary>
				/// Waits for the current execution to terminate.
				/// </summary>
				/// <remarks>
				/// This method blocks until the internal thread completes; without cancelling the operation.
				/// </remarks>
				virtual void EndExecute();
				#pragma endregion

			protected:

				/*--------------------------------------------------------------------------------
				 * Protected Event Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Protected Event Methods
				/// <summary>
				/// Raises the <see cref="TaskStart"/> event.
				/// </summary>
				/// <param name="e">
				/// An <see cref="EventArgs"/> event arguments instance. 
				/// </param>
				virtual void OnTaskStart(EventArgs^ e);
				/// <summary>
				/// Raises the <see cref="TaskCompleted"/> event.
				/// </summary>
				/// <param name="e">
				/// An <see cref="EventArgs"/> event arguments instance. 
				/// </param>
				virtual void OnTaskCompleted(EventArgs^ e);
				/// <summary>
				/// Raises the <see cref="TaskFailure"/> event.
				/// </summary>
				/// <param name="e">
				/// An <see cref="EventArgs"/> event arguments instance. 
				/// </param>
				virtual void OnTaskFailure(EventArgs^ e);
				/// <summary>
				/// Raises the <see cref="TaskCancelled"/> event.
				/// </summary>
				/// <param name="e">
				/// An <see cref="EventArgs"/> event arguments instance. 
				/// </param>
				virtual void OnTaskCancelled(EventArgs^ e);
				/// <summary>
				/// Raises the <see cref="TaskException"/> event.
				/// </summary>
				/// <param name="e">
				/// An <see cref="ExceptionEventArgs"/> event arguments instance containing
				/// the exception instance that was caught.
				/// </param>
				virtual void OnTaskException(ExceptionEventArgs^ e);
				/// <summary>
				/// Raises the <see cref="ProgressUpdate"/> event.
				/// </summary>
				/// <param name="e">
				/// A <see cref="ProgressEventArgs"/> event arguments instance containing
				/// the current execution status.
				/// </param>
				virtual void OnProgressUpdate(ProgressEventArgs^ e);
				/// <summary>
				/// Raises the <see cref="SubProgressUpdate"/> event.
				/// </summary>
				/// <param name="e">
				/// A <see cref="ProgressEventArgs"/> event arguments instance containing
				/// information on the execution of a sub-task.
				/// </param>
				virtual void OnSubProgressUpdate(ProgressEventArgs^ e);
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Protected Abstract Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Protected Abstract Methods
				/// <summary>
				/// Executes the task being implemented.
				/// </summary>
				/// <remarks>
				/// When the <see cref="BeginExecute"/> method is called, it creates a <see cref="Thread"/> instance and 
				/// invokes an internal method for executing the thread.  This internal method uses a loop to 
				/// perform a call to the descendant implementation of the <see cref="ExecuteTask"/> method and the <see cref="ExecuteSingleTaskAction"/> 
				/// method.  If either method returns <b>true</b>, the internal loop will exit and the thread may 
				/// terminate.
				/// 
				/// The <see cref="ExecuteTask"/> abstract method is intended to contain the particular task which is intended to run 
				/// asynchronously.  A child implementation may utilize any and all events defined on the base 
				/// class, allowing progress update stati during execution.  
				///
				/// It is not neccessary for the task to complete within the function definition; the wrapping loop 
				/// will re-invoke the function on each pass, so only a return value if <b>true</b> is needed to 
				/// terminate the thread loop.
				///
				/// Implementors may use the <see cref="ExecuteTask"/> method and/or the <see cref="ExecuteSingleTaskAction"/> method to perform
				/// threaded operations.  The <b>ExecuteSingleTaskAction</b> method may be useful for performing one 
				/// or more sub-tasks within the main operation.
				///
				/// Important: Any blocking code within the implementation will block the thread loop, thus preventing
				/// the cancellation of the operation.  All implementations should respond to the value of the 
				/// <see cref="Cancelled"/> property when <b>true</b>.
				/// </remarks>
				/// <returns>
				/// <b>true</b> if the task has completed and the executing thread may be terminated.
				/// </returns>
				virtual bool ExecuteTask() abstract;
				/// <summary>
				/// Executes a sub-task or portion of the main task being implemented.
				/// </summary>
				/// <remarks>
				/// When the <see cref="BeginExecute"/> method is called, it creates a <see cref="Thread"/> instance and 
				/// invokes an internal method for executing the thread.  This internal method uses a loop to 
				/// perform a call to the descendant implementation of the <see cref="ExecuteTask"/> method and the <see cref="ExecuteSingleTaskAction"/> 
				/// method.  If either method returns <b>true</b>, the internal loop will exit and the thread may 
				/// terminate.
				/// 
				/// The <see cref="ExecuteTask"/> abstract method is intended to contain the particular task which is intended to run 
				/// asynchronously.  A child implementation may utilize any and all events defined on the base 
				/// class, allowing progress update stati during execution.  
				///
				/// It is not neccessary for the task to complete within the function definition; the wrapping loop 
				/// will re-invoke the function on each pass, so only a return value if <b>true</b> is needed to 
				/// terminate the thread loop.
				///
				/// Implementors may use the <see cref="ExecuteTask"/> method and/or the <see cref="ExecuteSingleTaskAction"/> method to perform
				/// threaded operations.  The <b>ExecuteSingleTaskAction</b> method may be useful for performing one 
				/// or more sub-tasks within the main operation.
				///
				/// Important: Any blocking code within the implementation will block the thread loop, thus preventing
				/// the cancellation of the operation.  All implementations should respond to the value of the 
				/// <see cref="Cancelled"/> property when <b>true</b>.
				/// </remarks>
				/// <returns>
				/// <b>true</b> if the task has completed and the executing thread may be terminated.
				/// </returns>
				virtual bool ExecuteSingleTaskAction() abstract;
				#pragma endregion

			private:

				/*--------------------------------------------------------------------------------
				 * Private Member Declarations
				 *------------------------------------------------------------------------------*/
				#pragma region Private Member Declarations

				Thread^	_executionThread;
				bool	_executionFlag;
				bool	_cancelIndicator;

				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Private Methods / Functions
				 *------------------------------------------------------------------------------*/
				#pragma region Private Methods / Functions

				void	ExecuteTaskThread();
				void	TerminateThreadExecution();

				#pragma endregion

			};
		}
	}
}